# $Id$

"""
sk/adminraid.py
---------------

The in-raid update interface
"""

__author__ = 'Pat Smith <pat@waldosmith.com>'
__docformat__ = 'restructuredtext en'
__version__ = '$Revision$'[11:-2]


from datetime import datetime, timedelta
from exceptions import ValueError
from django import forms
from django.contrib.auth.decorators import login_required
from django.template import Context, loader
from django.http import HttpResponse
from monulu.raid.models import Raid, Character, CharacterClass, Boss, Item, Raider
from monulu.sk.models import SKSuicide, SKInstance, SKStart

from RaidRank import RaidRank

class RaidAdminForm(forms.Form):
    bossid = forms.ChoiceField(label=u'Boss')
    lootitems = forms.ChoiceField(label=u'Loot')
    character = forms.ChoiceField(label=u'Character', required=False)
    newchar = forms.CharField(label=u'New Character', required=False)
    classes = forms.ChoiceField(label=u'Class', required=False)

    def __init__(self, raid, request=None, **kwargs):
        self.request = request
        if request and self.request.method == "POST":
            kwargs['data'] = self.request.POST
            print self.request.POST.get('char')
            print self.request.POST.get('action')
        else:
            kwargs['data'] = {}
        bosses = Boss.objects.filter(instance=raid.instance)
        bid = kwargs['data'].get('bossid')
        if not bid:
            boss = bosses[0]
        else:
            boss = Boss.objects.get(pk=bid)

        loots = Item.objects.filter(boss=boss)
        lootchoices = [(i.id,i.__unicode__()) for i in loots]
        super(RaidAdminForm, self).__init__(**kwargs)
        choices = [(r.id,r.__unicode__()) for r in bosses]
        self.fields['bossid'].choices = choices
        self.fields['lootitems'].choices = lootchoices
        self.fields['character'].choices = [(c.id, c.name) for c in Character.objects.all()]
        self.fields['classes'].choices = [(c.id, c.name) for c in CharacterClass.objects.all()]

@login_required
def adminraid(request, raid_id):
    raid = Raid.objects.get(pk=raid_id)
    yesterday = datetime.today() - timedelta(5) # list raids up to x days old 
    raids = Raid.objects.filter(start_time__gte=yesterday).order_by('-start_time')
    raiders = getRaiders(raid)
    if request.method == 'POST':
        raidform = RaidAdminForm(raid, request)
        is_valid = raidform.is_valid()
        if not is_valid:
            for f in raidform:
                print f.errors
        action = request.POST.get('action')
        confirmedlist = [int(c) for c in request.POST.getlist('confirmed')]
        setConfirmed(raiders, confirmedlist) 
        if action == 'Add to raid':
            addNewRaider(raid, raidform.cleaned_data['character'])
            raiders = getRaiders(raid)
        elif action == 'Assign loot and suicide':
            assignLoot(raid, request.POST.get('selectedchar'), raidform.cleaned_data['lootitems']) 
            raiders = getRaiders(raid)
        elif action == 'Assign loot':
            assignLoot(raid, request.POST.get('selectedchar'), raidform.cleaned_data['lootitems'], False) 
            raiders = getRaiders(raid)
        elif action == 'New Character':
            try:            
                charkey = createCharacter(raid, raidform.cleaned_data['newchar'], raidform.cleaned_data['classes'])
                addNewRaider(raid, charkey)
            except:
                pass
            raiders=getRaiders(raid)
    else:
        raidform = RaidAdminForm(raid)
    t = loader.get_template('sk/adminraid.html')
    c = Context({'form':raidform,'raids':raids, 'raid':raid, 'raiders':raiders })
    return HttpResponse(t.render(c))

def setConfirmed(raiders, confirmedlist):
    for raider in raiders:
        if raider.char.character.id in confirmedlist:
            raider.char.confirmed = True
        else:
            raider.char.confirmed = False
        raider.char.save()
        
def getRaiders(raid):
    """Gets a list of all raiders signed for a raid, both confirmed and unconfirmed"""
    ski = SKInstance.objects.get(instance=raid.instance)
    ranks = ski.sklist.getRanks(raid.id)
    raiders=[]
    for rank in ranks:
        char = Character.objects.get(pk=rank[0])
        raider = Raider.objects.filter(raid=raid, character=char)
        if not raider:
            continue
        raider = raider[0]
        raiders.extend([RaidRank(rank[0], 
                        raider,
                        rank[1],
                        True,
                        SKSuicide.objects.filter(raid=raid, character=char))])
    return raiders       

def addCharToSKList(raid, char):
    if SKStart.objects.filter(character=char):
        return
    ski = SKInstance.objects.get(instance=raid.instance)
    sks = SKStart()
    sks.character = char
    sks.sklist = ski.sklist
    sks.initial_rank = getNextSKStart()
    sks.save()
    
def createCharacter(raid, charname, classkey):
    if not charname:
        raise ValueError, 'no character name provided'
    if Character.objects.filter(name=charname):
        raise ValueError, 'character name already exists'
    cclass = CharacterClass.objects.get(pk=classkey)
    if not cclass:
        raise ValueError, 'Character class not recognised'
    char = Character()
    char.character_class = cclass
    char.name = charname
    char.save()
    addCharToSKList(raid, char) 
    return char.pk

def addNewRaider(raid, charkey):
    char = Character.objects.get(pk=charkey)
    if not raid.isInRaid(char):
        raider = Raider()
        raider.raid = raid
        raider.character = char
        raider.signup_date = datetime.now()
        raider.confirmed = True
        raider.note = "by officer"
        raider.save()
        addCharToSKList(raid, char)

def getNextSuicideOrder():
    from django.db import connection
    cursor = connection.cursor()
    cursor.execute("SELECT count(skorder) FROM sk_sksuicide")
    if (cursor.fetchone()[0] == 0):
        # There haven't been any suicide claims yet
        return 1
    cursor.execute("SELECT max(skorder) FROM sk_sksuicide")
    row = cursor.fetchone()
    return int(row[0])+1

def getNextSKStart():
    from django.db import connection
    cursor = connection.cursor()
    cursor.execute("SELECT count(initial_rank) FROM sk_skstart")
    if (cursor.fetchone()[0] == 0):
        # The SKSTART list is currently empty
        return 1
    cursor.execute("SELECT max(initial_rank) FROM sk_skstart")
    row = cursor.fetchone()
    return int(row[0])+1

def assignLoot(raid, charkey, itemkey, is_suicide=True, note=''):
    ski = SKInstance.objects.get(instance=raid.instance)
    char = Character.objects.get(pk=charkey)
    item = Item.objects.get(pk=itemkey)
    suicide = SKSuicide()
    suicide.raid = raid
    suicide.character = char
    suicide.boss = item.boss
    suicide.item = item
    suicide.note = note
    suicide.sklist = ski.sklist
    suicide.is_suicide = is_suicide
    suicide.skorder = getNextSuicideOrder()
    suicide.save()

